<template>
	<div :class="{
		[prefixCls+'-table']:true,
		[prefixCls+'-table-border']:border,
		[prefixCls+'-table-stripe']:stripe,
		[prefixCls+'-table-fixed-top']:height,
		[prefixCls+'-table-'+size]:size,
		[prefixCls+'-table-ellipsis']:ellipsis,
		}" 
		:style="height?'height:'+height+'px':''">
		<div :class="{[prefixCls+'-table-header']:true}" ref="header" v-if="showHeader">
			<table>
				<colgroup>
					<col v-for="(col,index) in colWidth" :key="index" :width="col" />
				</colgroup>
				<TableHead
				:columns="columns"
				:sortCurrent="sortCurrent"
				:sortCls="sortCls"
				:selected="selected"
				:height="height">
				</TableHead>
			</table>
		</div>
		<div :class="{[prefixCls+'-table-body']:true,'scrolling':height}" :style="setBodyHeight" ref="body" @scroll="sysHandleScroll()" @mouseover="changeFlag(0)">
			<table ref="table">
				<colgroup>
					<col v-for="(col,index) in colWidth" :key="index" :width="col" v-if="col!=17" />
				</colgroup>
				<tbody>
					<template v-if="tableData.length>0">
						<template v-for="(col,index) in tableData">
							<tr :key="index" 
							@mouseenter="hoverIndex=index" 
							@mouseleave="hoverIndex=-1" 
							@click="rowClick(col,index)"
							:class="{[col.trClass]:col.trClass,[prefixCls+'-table-tr-hover']:index==hoverIndex&&hover,'extend-open':toggle[index]}">
								<template v-for="(d,i) in columns">
									<td :key="i"
										@click="cellClick(col,index,d,col[d.prop])" 
										:class="[d.align,d.fixed?'hidden':'']"
										v-if="!d.$children.length>0"
										>
										<div class="cell" v-if="d.type=='selection'">
											<mj-checkbox 
												v-model="selected.arr" 
												:value="index" 
												@change="selectedCheckbox" 
												:disabled='col.disabled'
											>
											</mj-checkbox>
										</div>
										<div class="cell" v-else-if="d.type=='index'">{{index+1}}</div>
										<div class="cell" v-else>
											<mj-tooltip class-name="mj-table-tooltip" :content="contentText" direction="top-left" :delay="300" :maxWidth="500">
												<Tabletd
													:row="col"
													:colWidth="colWidth"
													:showTooltip="showTooltip"
													:column="d"
													:columnIndex="i"
													:index="index"
													:txt="col[d.prop]"
													:showHideExtend="showHideExtend"
													:toggle="toggle[index]===undefined?defaultToggle:toggle[index]"
													@hover="computedWidth">
												</Tabletd>
											</mj-tooltip>
										</div>
									</td>
								</template>
								
							</tr>

						    <!--扩展列-->
						    <tr
						      :key="'tr' + index" 
						      v-if="extendColums.length>0"
						      class="extend" v-show="toggle[index]===undefined?defaultToggle:toggle[index]"
						      @click="rowClick(col,index)">
						      <template v-for="(d,i) in extendColums">
							      	<td :colspan="columns.length">
										<div class="cell">
											<Tabletd 
												:row="col"
												:column="d"
												:index="index"
												:txt="d">
											</Tabletd>
										</div>
							      	</td>
						      </template>
						    </tr>

							<!--二级children-->
							<template v-if="hasChild">
								<tr
								v-for="(item,cIndex) in col.children"
								v-show="toggle[index]===undefined?defaultToggle:toggle[index]"
								class="tr-child"
								@mouseenter="hoverIndex='child'+index+cIndex" 
								@mouseleave="hoverIndex=-1"
								@click="rowClick(item,cIndex)"
								:class="{[item.trClass]:item.trClass,[prefixCls+'-table-tr-hover']:'child'+index+cIndex==hoverIndex&&hover}">
									<td v-for="(d,i) in columns" :key="'childTd'+i" :class="[d.align,,d.fixed?'hidden':'']" @click="cellClick(item,cIndex,d,item[d.prop])">
										<div class="cell">
											<Tabletd
												:row="item"
												:column="d"
												:index="cIndex"
												:txt="item[d.prop]">
											</Tabletd>
										</div>
									</td>
								</tr>
							</template>
						</template>
					</template>
					<tr v-else>
						<td :colspan="columns.length" class="empty">
							{{emptyText}}
						</td>
					</tr>
				</tbody>
			</table>
		</div>

		<!-- 左侧浮动列结构 -->
		<div 
		:class="[prefixCls+'-table-fixed-left',fixedLeft.isScrolling?'is-scrolling':'']"v-if="fixedLeft.columns.length>0" 
		:style="'width:'+fixedLeft.width+'px'">
			<div :class="{[prefixCls+'-table-header-fixed']:true}">
				<table>
					<colgroup>
						<col v-for="(col,index) in colWidth" :key="index" :width="col" />
					</colgroup>
					<TableHead
					:columns="columns"
					:sortCurrent="sortCurrent"
					:sortCls="sortCls"
					:selected="selected"
					:height="height"
					fixed="left">
					</TableHead>
				</table>
			</div>
			<div :class="{[prefixCls+'-table-body-fixed']:true,'scrolling':height}" :style="'height:'+fixedBodyHeight+'px'" ref="bodyfixedLeft" @scroll="exterHandleScrollLeft()" @mouseover="changeFlag(1)">
				<table>
					<colgroup>
						<col v-for="(col,index) in fixedLeft.colWidth" :key="index" :width="col" />
					</colgroup>
					<tbody>
						<tr v-for="(col,index) in tableData" :key="index" 
						@mouseenter="hoverIndex=index" 
						@mouseleave="hoverIndex=-1"
						@click="rowClick(col,index)"
						:class="{[prefixCls+'-table-tr-hover']:index==hoverIndex&&hover}">
							<td v-for="(d,i) in fixedLeft.columns" :key="i" :class="d.align" @click="cellClick(col,index,d,col[d.prop])">
								<div class="cell" v-if="d.type=='selection'">
									<mj-checkbox v-model="selected.arr" :value="index" @change="selectedCheckbox" :disabled='col.disabled'></mj-checkbox>
								</div>
								<div class="cell" v-else-if="d.type=='index'">{{index+1}}</div>
								<div class="cell" v-else>
									<!-- {{col[d.prop]}} -->
									<mj-tooltip class-name="mj-table-tooltip" :content="contentText" direction="top-left" :delay="300" :maxWidth="500">
										<Tabletd 
											:row="col"
											:colWidth="fixedLeft.colWidth"
											:showTooltip="showTooltip"
											:column="d"
											:columnIndex="i"
											:index="index"
											:txt="col[d.prop]"
											@hover="computedWidth">
										</Tabletd>
									</mj-tooltip>
								</div>
							</td>
						</tr>
					</tbody>
				</table>
			</div>
		</div>

		<!-- 右侧浮动列结构 -->
		<div 
		:class="[prefixCls+'-table-fixed-right',fixedRight.isScrolling?'is-scrolling':'']" 
		v-if="fixedRight.columns.length>0" 
		:style="fixedRightStyle">
			<div :class="{[prefixCls+'-table-header-fixed']:true}">
				<table>
					<colgroup>
						<col v-for="(col,index) in fixedRight.colWidth" :key="index" :width="col" />
					</colgroup>
					<TableHead
					:columns="columns"
					:sortCurrent="sortCurrent"
					:sortCls="sortCls"
					:selected="selected"
					:height="height"
					fixed="right">
					</TableHead>
				</table>
			</div>
			<div :class="{[prefixCls+'-table-body-fixed']:true,'scrolling':height}" :style="'height:'+fixedBodyHeight+'px'" ref="bodyfixedRight" @scroll="exterHandleScrollRight()" @mouseover="changeFlag(2)">
				<table>
					<colgroup>
						<col v-for="(col,index) in fixedRight.colWidth" :key="index" :width="col" />
					</colgroup>
					<tbody>
						<tr v-for="(col,index) in tableData" :key="index" 
						@mouseenter="hoverIndex=index" 
						@mouseleave="hoverIndex=-1"
						@click="rowClick(col,index)"
						:class="{[prefixCls+'-table-tr-hover']:index==hoverIndex&&hover}">
							<td v-for="(d,i) in fixedRight.columns" :key="i" :class="d.align" @click="cellClick(col,index,d,col[d.prop])">
								<div class="cell" v-if="d.type=='index'">{{index+1}}</div>
								<div class="cell" v-else>
									<!-- {{col[d.prop]}} -->
									<mj-tooltip class-name="mj-table-tooltip" :content="contentText" direction="top-left" :delay="300" :maxWidth="500">
										<Tabletd 
											:row="col"
											:colWidth="fixedRight.colWidth"
											:showTooltip="showTooltip"
											:column="d"
											:columnIndex="i"
											:index="index"
											:txt="col[d.prop]"
											@hover="computedWidth">
										</Tabletd>
									</mj-tooltip>
								</div>
							</td>
						</tr>
					</tbody>
				</table>
			</div>
		</div>

		<div style="display: none;">
			<slot></slot>
		</div>

	</div>
</template>

<script>
import {prefixCls} from '../prefix'
import Tabletd from './td'
import TableHead from './head'

export default {
	name: `${prefixCls}Table`,
	components:{TableHead, Tabletd},
	props: {
		data: Array,
		border: {
			type: Boolean,
			default: false
		},
		stripe: {
			type: Boolean,
			default: false
		},
		showHeader: {
			type: Boolean,
			default: true
		},
		hover: {
			type: Boolean,
			default: true
		},
		height: String,
		emptyText: {
			type: String,
			default: '暂无数据'
		},
		extendToggle: { // 默认展开扩展
			type: Boolean,
			default: false
		},
		lazyLoad: Function,
		hasChild: Boolean,
		size: String,
		ellipsis: {
			type: Boolean,
			default: false
		},
		showTooltip: {
			type: Boolean,
			default: false
		},
	},
	data() {
		return {
			prefixCls: prefixCls,
			tableData:this.data,//table数据
			columns:[],	//表头列数据
			colWidth:[],//列宽,
			hoverIndex: -1,//tr hover
			bodyHeight:'',//表格body高度
			fixedLeft:{
				width:0,//含有浮动列的总宽度
				columns:[],//浮动左侧列数据
				colWidth:[],
				isScrolling:false, //横向滚动中，添加阴影
			},
			fixedRight:{
				width:0,
				columns:[],//浮动右侧列数据
				colWidth:[],
				isScrolling:false, //横向滚动中，添加阴影
			},
			flag: 0,//同步滚动条
			fixedBodyHeight:'',//浮层的body高度
			selected:{
				all:false,//全选
				rows:[],// 已选择的行数据
				arr:[],// 已选择的行val(这里用的是index)
			},
			sortType: '', //排序
			sortCurrent:'',	//当前排序字段
			extendColums:[],//扩展列
			defaultToggle: this.extendToggle, // 默认展开或收起状态
			toggle: {}, // {1: true, 2: false, 0: false} // 对应每行展开或收起状态
			children:[],
			contentText: '', // tooltips文字
			showVerticalScrollBar: false,
		}
	},
	mounted() {
		// console.log('%c MASTER THIS:','background:green',this)
		this.init()
	    window.addEventListener('resize', () => {
	    	this.setColWidth()
	    	this.setFixedBodyHeight()
	    	this.fixedRightScrolling()
	    })
	},
	watch: {
		data:{
			handler(val){
				this.tableData = val;
				this.toggleSelection(false);
				this.fixedBody();
			},
			deep:true
		}
	},
	methods: {
		init() {
			this.getColumn()
			this.setColWidth()
			this.setFixedBodyHeight()
    		this.fixedRightScrolling()// 横向滚动条，fixed右侧添加阴影 
		},
		getColumn() {
			// console.log(this)
			// 获取列信息
			let layer = 0
			this.$children.map((d,colIndex)=>{
				if(d.$options.componentName == 'Column') {
					// 区分扩展列和非扩展列
					d['_layer'] = layer
					if(d.type != 'extend') {
						this.columns.push(d)
					}else{
						this.extendColums.push(d)
					}

					// 多级表头
					if(d.$children.length>0) {
						d.$children.map(item => {
							item['_layer'] = layer+1
							item['_child'] = true
							this.columns.push(item)
						})
					}

					if(d.fixed == 'left') {
						this.fixedLeft.columns.push(d)
						this.fixedLeft.colWidth.push(d.width)
						this.fixedLeft.width+=Number(d.width)
					}
					if(d.fixed == 'right') {
						this.fixedRight.columns.push(d)
						this.fixedRight.colWidth.push(d.width)
						this.fixedRight.width+=Number(d.width)
					}
				}
			})
    		/**
    		 * 有浮动列时候，重新排列，left的排到左侧，right的排到右侧。
    		 */
        	if(this.fixedLeft.columns.length>0) {
        		this.fixedLeft.columns.map((item,index)=>{
        			this.columns.map((c,i)=>{
        				if(item.label == c.label && c.fixed) {
        					this.columns.splice(i,1)
        				}
        			})
	    			this.columns.unshift(item)
        		})
        	}
        	if(this.fixedRight.columns.length>0) {
        		this.fixedRight.columns.map((item,index)=>{
        			this.columns.map((c,i)=>{
        				if(item.label == c.label && c.fixed) {
        					this.columns.splice(i,1)
        				}
        			})
	    			this.columns.push(item)
        		})
        	}
			// console.log('%c 列数组：','background:blue',this.columns)
			// console.log('%c 浮动Left列：','background:blue',this.fixedLeft.columns)
			// console.log('%c 浮动Right列：','background:blue',this.fixedRight.columns)
		},
		setColWidth() {
			this.$nextTick(()=>{
				// 设置列宽度
				const w = this.$el.clientWidth,//表格总宽度
					  l = this.columns.length//column数量
				// console.log(w,l)
				let newWidth = w-19,
					newLength = l;
				this.columns.map((d)=>{
					// 多级表头，含有子组件的表头不计入宽度分配
					if(d.$children.length>0){
						newLength--
					}
				})
				this.colWidth = []
				this.columns.map((d)=>{
					// 多级表头，含有子组件的表头不计入宽度分配
					if(d.$children.length == 0) {
						// 设置列表
						if(d.width) {
							// 有设置宽度
							this.colWidth.push(d.width)
						}else{
							// 没有设置宽度，自动计算
							let pfw = Number((newWidth/newLength).toFixed(0))
							let n = Number(d.minWidth?d.minWidth:80)
							this.colWidth.push(pfw>n?pfw:n)
						}
					}
				})
				// 表头固定情况下，col添加一列 17
				if(this.height) {
					this.colWidth.push('17')
				}
			})
		},
        changeFlag(flag) {
			this.flag = flag
		},
        sysHandleScroll() {
        	if (this.flag == 0) {
        		const $l = this.$refs.bodyfixedLeft
        		const $r = this.$refs.bodyfixedRight
        		const $b = this.$refs.body
        		const $h = this.$refs.header
        		const $t = this.$refs.table
        		if($l) {
        			$l.scrollTop = $b.scrollTop 
        		}
        		if($r) {
        			$r.scrollTop = $b.scrollTop 
        		}
        		$h.scrollLeft = $b.scrollLeft
				// 横向滚动条，fixed左侧添加阴影        		
        		if($b.scrollLeft > 0) {
        			this.fixedLeft.isScrolling = true
        		}else{
        			this.fixedLeft.isScrolling = false
        		}
        		// 横向滚动条，fixed右侧添加阴影 
        		this.fixedRightScrolling()
        	}
        },
        exterHandleScrollLeft() {
        	if (this.flag == 1) {
        		const $l = this.$refs.bodyfixedLeft
        		const $r = this.$refs.bodyfixedRight
        		const $b = this.$refs.body
	        	$b.scrollTop = $l.scrollTop
        		if($r) {
        			$r.scrollTop = $l.scrollTop 
        		}
        	}
        },
        exterHandleScrollRight() {
        	if (this.flag == 2) {
        		const $l = this.$refs.bodyfixedLeft
        		const $r = this.$refs.bodyfixedRight
        		const $b = this.$refs.body
	        	$b.scrollTop = $r.scrollTop
        		if($l) {
        			$l.scrollTop = $r.scrollTop 
        		}
        	}
        },
        setFixedBodyHeight() {
	        // 存在浮层的情况下，设置浮层body的高度
	        this.$nextTick(()=>{
	        	if(this.fixedLeft.columns.length>0 || this.fixedRight.columns.length>0) {
		        	if(this.$refs.body==undefined) {
		        		return false
		        	}
		        	const b = this.$refs.body.getBoundingClientRect()
		        	let total=0
		        	this.colWidth.map((d)=>{
		        		total+=Number(d)
		        	})
		        	// body外壳小于table宽度，表示有滚动条，设置浮层高度减去滚动条高度
		        	if(b.width < total) {
		        		this.fixedBodyHeight = this.bodyHeight - 17
		        	}else{
		        		this.fixedBodyHeight = this.bodyHeight
		        	}
	        	}
    		})
        },
        selectCheckedAll(val) {
        	// checkbox全选
        	if(val){
        		this.selected.arr = []
        		this.selected.rows = []
        		this.tableData.map((d,i)=>{
        			if(!d.disabled) {
        				this.selected.arr.push(i)
        				this.selected.rows.push(d)
        			}
        		})
        	}else{
        		this.selected.rows = []
        		this.selected.arr = []
        	}
        	// console.log('已选择：',this.selected)
        },
        selectedCheckbox(val) {
        	// checkbox单选
        	this.selected.rows = []
        	const arr = val.sort()
        	arr.map((d)=>{
        		this.selected.rows.push(this.tableData[d])
        	})
        	let len = 0
        	this.tableData.map((d,i)=>{
        		if(!d.disabled) {
        			len++
        		}
        	})
        	if(this.selected.rows.length == len) {
        		this.selected.all = true
        	}else{
        		this.selected.all = false
        	}
        },
		getSelectAll () {
			return this.selected.rows
		},
	    toggleSelection (boolean) {
	      // boolean=true全选，false全不选
	      if (boolean) {
	        // 用于多选表格，切换所有行的选中状态
	        // this.selected.rows = [...this.tableData]
	        // this.selectChecked = 'checked'
    		this.selected.arr = []
    		this.selected.rows = []
    		this.selected.all = true
    		this.tableData.map((d,i)=>{
    			if(!d.disabled) {
    				this.selected.arr.push(i)
    				this.selected.rows.push(d)
    			}
    		})
	      } else {
	        // 用于多选表格，清空用户的选择
	        this.selected.arr = []
	        this.selected.rows = []
	        this.selected.all = false
	        // this.selectChecked = 'un-select'
	      }
	    },
	    toggleRowSelection (row, selected) {
	      // 用于多选表格，切换某一行的选中状态，如果使用了第二个参数，则是设置这一行选中与否（selected 为 true 则选中）row, selected
	      const index = this.selected.arr.indexOf(row)
	      if (selected === false) {
	        // 取消勾选当前行
	        if (index !== -1) {
	          this.selected.rows.splice(index, 1)
	          this.selected.arr.splice(index, 1)
	        }
	        this.selected.all = false
	      } else {
	        // 勾选当前行，没有时添加。有时不重复添加
	        if (index === -1) {
	          this.selected.rows.push(this.tableData[row])
	          this.selected.arr.push(row)
	        }
        	let len = 0
        	this.tableData.map((d,i)=>{
        		if(!d.disabled) {
        			len++
        		}
        	})
        	if(this.selected.rows.length == len) {
        		this.selected.all = true
        	}
	      }
	    },
        _orderBy(item, el, index,type){
        	if(!item.sortable && item.sortable!='custom') return false
        	this.sortCurrent = index
            if (item.sortable) {
                const $etl = el.target.classList
                const $etn = el.target.className
                // 是否在cell上点击排序循环，这上面不会传asc/desc
                if(type){
                	// console.log('直接点在三角上',type)
                	const parent = el.target.parentNode.parentNode
                	this.sortType = type
                	// 非服务端排序，则使用本地排序
		        	if(item.sortable!='custom') {
                		this.tableData.sort(this._sortBy(item.prop,type))
		        	}
                }else{
                	// console.log('在整个sort上循环点击,同时查看是否已有排序标记',$etn)
                	if($etn.indexOf('asc')>0){
                		this.sortType = 'desc'
                	}else if($etn.indexOf('desc')>0){
                		this.sortType = 'asc'
                	}else{
                		this.sortType = 'asc'
                	}
                	if(item.sortable!='custom') {
                		this.tableData.sort(this._sortBy(item.prop,this.sortType))
                	}
                }
            }
            // 排序后取消checkbox选择
            this.toggleSelection(false)
            this.$emit('sort-change',item._props,item.prop,this.sortType)
        },
        _sortBy(sortValue, sortType){
            let type
            sortType=='asc'?type=true:type=false
            //第一点击sortType为true即顺序，第二次点击为倒序
            return function (a, b) {
                var val1 = a[sortValue];
                var val2 = b[sortValue];
                if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
                    val1 = Number(val1);
                    val2 = Number(val2);
                }
                if (val1 < val2) {
                    // return -1;//顺序，倒序1
                    return type? -1 : 1
                } else if (val1 > val2) {
                    //return 1;
                    return type? 1 : -1
                } else {
                    return 0;
                }
            };
        },
        clearSort() {
        	// 清空排序由服务端控制，本地清除排序状态
        	this.sortType = ''
        	this.sortCurrent = ''
        },
        showHideExtend(index,row) {
        	// console.log('展开子内容',index,row)
			// 存在扩展时或有子级时
			if (this.extendColums.length > 0 || this.hasChild) {
				if (typeof this.toggle[index] === 'undefined') {
					this.$set(this.toggle, index, !this.defaultToggle)
				} else {
					this.toggle[index] = !this.toggle[index]
				}
				// 展开时，如果是懒加载
				if (this.toggle[index] && this.lazyLoad) {
					this.lazyLoad(row, child => {
						row.children = child
					})
				}
			}
        },
        fixedRightScrolling() {
    		// 横向滚动条，fixed右侧添加阴影 ,初始化时需判断一下
    		if(this.fixedRight.columns.length>0) {
	    		setTimeout(()=>{
		    		const $b = this.$refs.body
		    		const $t = this.$refs.table
		    		if($b==undefined && $t==undefined){
		    			return false
		    		}
		    		const $bWidth = $b.offsetWidth
		    		const $tWidth = $t.offsetWidth
	    			// console.log($b.scrollLeft,$tWidth , $bWidth)
	    			let _scrollWidth = 0
	    			this.height?_scrollWidth=17:''
		    		if($tWidth > $bWidth) {
			    		if($b.scrollLeft >= ($tWidth - $bWidth + _scrollWidth)) {
			    			this.fixedRight.isScrolling = false
			    		}else{
			    			this.fixedRight.isScrolling = true
			    		}
		    		}else{
		    			this.fixedRight.isScrolling = false
		    		}
	    		})
    		}
        },
        rowClick(row,index) {
        	// 行点击事件
        	this.$emit('row-click', row, index)
        },
        cellClick(row,index,column,cell) {
        	// td点击事件
        	if(column.prop){
        		this.$emit('cell-click',row,index,column._props,cell)
        	}
        },
		// td hover状态下有省略号时触发事件
		computedWidth(e,column,i,txt) { 
			// 36是左右边距
			const width = Number(column[i]) || 0;
			if(e.target.offsetWidth + 36 > width){
				this.contentText = txt
			} else {
				this.contentText = ''
			}
		},
		fixedBody() {
			this.$nextTick(() =>{
				if (!this.$refs.table || !this.tableData || this.tableData.length === 0) {
					this.showVerticalScrollBar = false;
				}else{
					const tableHeight = this.$refs.table.getBoundingClientRect().height
					this.showVerticalScrollBar = this.height && tableHeight > this.height ? true : false
				}
			})
		}
	},
    computed: {
        setBodyHeight() {
			this.$nextTick(()=>{
				const h = this.$refs.header.getBoundingClientRect()
				let bh = this.height-h.height
				this.bodyHeight = bh
			})
        	return 'height:'+this.bodyHeight+'px'
        },
        fixedRightStyle() {
        	return {width:this.fixedRight.width+'px',right:this.showVerticalScrollBar?'17px':''}
        },
        sortCls() {
        	return this.sortType
        },
    },
    destroyed() {
	    window.removeEventListener('resize', () => {
	    	this.setColWidth()
	    	this.setFixedBodyHeight()
	    	this.fixedRightScrolling()
	    })
    }
}
</script>